
package com.insigma.business.qrcode.merchant._provider.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;


import com.insigma.business.common.dto.CurrentUser;
import com.insigma.business.common.utils.CurrentUserUtil;
import com.insigma.business.qrcode.common.converter.CareWelfareMerchantDiscountProviderConverter;
import com.insigma.business.qrcode.common.dao.CommonAdminAreaDO;
import com.insigma.business.qrcode.common.dto.CommonFavoriteDO;
import com.insigma.business.qrcode.common.service.CommonAdminAreaService;
import com.insigma.business.qrcode.common._provider.CommonFavoriteProvider;
import com.insigma.business.qrcode.common.service.CommonFavoriteService;
import com.insigma.business.qrcode.common.template.BasePagingResponse;
import com.insigma.business.qrcode.common.util.AdminAreaCodeUtils;
import com.insigma.business.qrcode.common.util.BizCheckUtil;
import com.insigma.business.qrcode.common.util.BizException;
import com.insigma.business.qrcode.common.util.DateUtils;
import com.insigma.business.qrcode.common.util.ResponseUtils;
import com.insigma.business.qrcode.common.vo.BaseDeleteRequest;
import com.insigma.business.qrcode.common.vo.BaseResponse;
import com.insigma.business.qrcode.common.vo.RecordTypeEnum;
import com.insigma.business.qrcode.merchant.entity.CareWelfareMerchantEvaluationDO;
import com.insigma.business.qrcode.merchant.service.CareWelfareMerchantDiscountService;
import com.insigma.business.qrcode.merchant.service.CareWelfareMerchantInfoService;
import com.insigma.business.qrcode.merchant.dto.search.CareWelfareMerchantInfoBSearcher;
import com.insigma.business.qrcode.soldier.dto.SimpleApiRequest;
import com.insigma.business.qrcode.soldier.dto.SystemConfigService;
import com.insigma.business.qrcode.soldier.dto.UserStatusEnum;
import com.insigma.business.qrcode.soldier.dto.gov.BaseProviderImpl;
import com.insigma.business.qrcode.common.template.area.ServiceCallback;
import com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum;
import com.insigma.business.qrcode.soldier.entity.DataStatsCDO;
import com.insigma.business.qrcode.soldier.entity.MerchantUserDO;
import com.insigma.business.qrcode.soldier.request.BaseGetRequest;
import com.insigma.business.qrcode.merchant.dto.request.CareWelfareMerchantInfoSearchRequest;
import com.insigma.business.qrcode.soldier._provider.GovEmployeeProvider;
import com.insigma.business.qrcode.soldier.service.SoldierBasicInfoService;
import com.insigma.business.qrcode.soldier._provider.SoldierProvider;
import com.insigma.business.qrcode.soldier.service.SoldierService;
import com.insigma.business.qrcode.merchant._provider.CareWelfareMerchantInfoProvider;
import com.insigma.business.qrcode.merchant._provider.CareWelfareMerchantStreetProvider;
import com.insigma.business.qrcode.welfare.dto.*;
import com.insigma.business.qrcode.merchant.entity.CareWelfareMerchantDiscountDO;
import com.insigma.business.qrcode.merchant.entity.CareWelfareMerchantInfoDO;
import com.insigma.business.qrcode.welfare.entity.ScanCodeRecordDO;
import com.insigma.business.qrcode.welfare.service.*;
import com.insigma.business.qrcode.common.converter.CareWelfareMerchantInfoProviderConverter;
import com.insigma.business.qrcode.welfare.util.CommonCheckUtils;
import com.insigma.business.qrcode.welfare.util.LocationUtils;
import com.insigma.business.qrcode.welfare.util.PasswordUtils;
import com.insigma.business.qrcode.welfare.util.SycBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Slf4j
@Service
@Component("careWelfareMerchantInfoProvider")
public class CareWelfareMerchantInfoProviderImpl extends BaseProviderImpl implements CareWelfareMerchantInfoProvider {

    @Autowired
    private CareWelfareMerchantInfoService careWelfareMerchantInfoService;



    @Autowired
    private SoldierProvider soldierProvider;

    @Autowired
    private CommonAdminAreaService commonAdminAreaService;

    @Autowired
    private SoldierBasicInfoService soldierBasicInfoService;

    @Autowired
    @Lazy
    private SoldierService soldierService;

    @Autowired
    private MarketingSpotMaterialsService marketingSpotMaterialsService;

    @Autowired
    private GovEmployeeProvider govEmployeeProvider;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private ScanCodeRecordService scanCodeRecordService;

    @Autowired
    private CareWelfareMerchantDiscountService careWelfareMerchantDiscountService;

    @Autowired
    private CommonFavoriteService commonFavoriteService;


    @Value("${h5.host.url}")
    private String h5HostUrl;

    @Value("${h5.merchant.scan.base}")
    private String merchantScanBase;

    Cache<String, Map<String, CareWelfareMerchantBO>> cachedMerchants = CacheBuilder.newBuilder().expireAfterWrite(60L, TimeUnit.MINUTES).build();

    @Autowired
    private CareWelfareMerchantStreetProvider careWelfareMerchantStreetProvider;

    @Autowired
    private CommonFavoriteProvider commonFavoriteProvider;

    @Resource
    MerchantUserService merchantUserService;

    @Override
    public BasePagingResponse<List<CareWelfareMerchantInfoDTO>> searchCareWelfareMerchantInfo(final CareWelfareMerchantInfoSearchRequest searchRequest) {

        final BasePagingResponse<List<CareWelfareMerchantInfoDTO>> basePagingResponse = new BasePagingResponse<>();
        serviceTemplate.execute(basePagingResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(searchRequest, "查询分页CareWelfareMerchantInfo的请求参数不能为空");
            }

            @Override
            public void executeService() {
                CurrentUser currentUser = CurrentUserUtil.getCurrentUser();
                final CareWelfareMerchantInfoBSearcher careWelfareMerchantInfoBSearcher = CareWelfareMerchantInfoProviderConverter.convertRequestSO2Searcher(searchRequest);
                careWelfareMerchantInfoBSearcher.setSortKeyValueJoint("createDatetime_desc");
                PageHelper.startPage(searchRequest.getPageNo(), searchRequest.getPageSize());
                final List<CareWelfareMerchantInfoDO> careWelfareMerchantInfoDOList = careWelfareMerchantInfoService.search(careWelfareMerchantInfoBSearcher);
                PageInfo<CareWelfareMerchantInfoDO> pageInfo = new PageInfo<>(careWelfareMerchantInfoDOList);
                final List<CareWelfareMerchantInfoDTO> careWelfareMerchantInfoDTOList = CareWelfareMerchantInfoProviderConverter.convertResponseDOList2DTOList(careWelfareMerchantInfoDOList);
                if (CollectionUtils.isNotEmpty(careWelfareMerchantInfoDTOList)) {
                    for (CareWelfareMerchantInfoDTO merchantInfoDTO : careWelfareMerchantInfoDTOList) {
                        CommonFavoriteDO commonFavoriteDO = commonFavoriteService.getBySoldierIdAndTypeAndBizId(currentUser.getSoldierId(),"MERCHANT",merchantInfoDTO.getId());
                        merchantInfoDTO.setFavorite(commonFavoriteDO==null?false:true);
                        merchantInfoDTO.setFavoriteId(commonFavoriteDO==null?null:commonFavoriteDO.getId());
                        CareMerchantStreetBO cachedStreet = careWelfareMerchantStreetProvider.getCachedStreet(merchantInfoDTO.getId());
                        merchantInfoDTO.setStreet(cachedStreet);
                        List<CareWelfareMerchantDiscountDO> list = careWelfareMerchantDiscountService.listByMerchantId(merchantInfoDTO.getId());
                        merchantInfoDTO.setDiscounts(CareWelfareMerchantDiscountProviderConverter.convertResponseDOList2DTOList(list));
                    }
                }

                ResponseUtils.buildSuccessPagingResponse(basePagingResponse, careWelfareMerchantInfoDTOList, searchRequest, pageInfo.getTotal());
            }

            @Override
            public ScenarioCodeEnum getScenarioEnum() {
                return ScenarioCodeEnum.CARE_WELFARE_MERCHANT_INFO_SEARCH;
            }
        });

        return basePagingResponse;
    }

    @Override
    public BaseResponse<CareMerchantStats> getMerchantStats(SimpleApiRequest request) {
        CareMerchantStats stats = new CareMerchantStats();
        CareWelfareMerchantInfoBSearcher searcher = new CareWelfareMerchantInfoBSearcher(1, 20);
        stats.setMerchantCount(careWelfareMerchantInfoService.countMerchant(searcher));
        searcher.setPublished(true);
        stats.setPublishedCount(careWelfareMerchantInfoService.countMerchant(searcher));
        searcher.setPublished(false);
        stats.setUnpublishedCount(careWelfareMerchantInfoService.countMerchant(searcher));
        stats.setUnconfirmedCount(0);
        stats.setTrafficCount(careWelfareMerchantInfoService.countMerchantTraffic());

        stats.setMerchantTypeMap(buildMerchantTypeMap(request));
        stats.setMerchantTypeTrafficMap(buildMerchantTypeTrafficMap(request));
        stats.setMerchantAddMap(buildMerchantAddMap(request));
        stats.setTopMerchantMap(buildTopMerchantMap(request));
        return ResponseUtils.buildSuccessResponse(stats);
    }

    private LinkedHashMap<String, Integer> buildTopMerchantMap(SimpleApiRequest request) {
        List<DataStatsCDO> dataStatsCDOS = careWelfareMerchantInfoService.countMerchantTopTraffic();

        LinkedHashMap<String, Integer> result = Maps.newLinkedHashMap();
        for (DataStatsCDO dataStatsCDO : dataStatsCDOS) {
            result.put(dataStatsCDO.getItemName(), dataStatsCDO.getItemCount());
        }
        return result;
    }

    private LinkedHashMap<String, Integer> buildMerchantAddMap(SimpleApiRequest request) {
        Date nowMonthStart = DateUtils.getTimesMonthmorning();
        CareWelfareMerchantInfoBSearcher searcher = new CareWelfareMerchantInfoBSearcher(1, 20);
        searcher.setCreateStartTime(nowMonthStart);
        searcher.setCreateEndTime(new Date());
        int nowMonthCount = careWelfareMerchantInfoService.countMerchant(searcher);

        Date preMonthDate = DateUtils.getTimesNearMonthMorning(-1);
        searcher.setCreateStartTime(preMonthDate);
        searcher.setCreateEndTime(nowMonthStart);
        int preMonthCount = careWelfareMerchantInfoService.countMerchant(searcher);


        Date prePreMonthDate = DateUtils.getTimesNearMonthMorning(-2);
        searcher.setCreateStartTime(prePreMonthDate);
        searcher.setCreateEndTime(preMonthDate);
        int prePreMonthCount = careWelfareMerchantInfoService.countMerchant(searcher);

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        LinkedHashMap<String, Integer> result = Maps.newLinkedHashMap();
        result.put(dateFormat.format(prePreMonthDate), prePreMonthCount);
        result.put(dateFormat.format(preMonthDate), preMonthCount);
        result.put(dateFormat.format(nowMonthStart), nowMonthCount);
        return result;
    }

    private LinkedHashMap<String, Integer> buildMerchantTypeTrafficMap(SimpleApiRequest request) {
        List<DataStatsCDO> dataStatsCDOS = careWelfareMerchantInfoService.countMerchantTypeTraffic();

        LinkedHashMap<String, Integer> result = Maps.newLinkedHashMap();
        for (DataStatsCDO dataStatsCDO : dataStatsCDOS) {
            result.put(MerchantTypeEnum.getByEnumName(dataStatsCDO.getItemName()).getDesc(), dataStatsCDO.getItemCount());
        }
        return result;
    }

    private LinkedHashMap<String, Integer> buildMerchantTypeMap(SimpleApiRequest request) {
        LinkedHashMap<String, Integer> result = Maps.newLinkedHashMap();
        List<DataStatsCDO> dataStatsCDOS = careWelfareMerchantInfoService.countMerchantType();
        for (DataStatsCDO dataStatsCDO : dataStatsCDOS) {
            result.put(MerchantTypeEnum.getByEnumName(dataStatsCDO.getItemName()).getDesc(), dataStatsCDO.getItemCount());
        }
        return result;
    }

    @Override
    public BasePagingResponse<List<CareWelfareMerchantInfoDTO>> searchMerchantInfoBySoldier(CareWelfareMerchantInfoSearchRequest request) {
        BizCheckUtil.checkNotNull(request, "request的请求参数不能为空");
        BizCheckUtil.checkNotNull(request.getSoldierAdminAreaCode(), "老兵地区的请求参数不能为空");

        final CareWelfareMerchantInfoBSearcher searcher = CareWelfareMerchantInfoProviderConverter.convertRequestSO2Searcher(request);

        String adminCode = searcher.getSoldierAdminAreaCode();
        adminCode = adminCode.substring(0, 6);
        searcher.setSoldierAdminAreaCode(AdminAreaCodeUtils.fillAreaCode(adminCode));

        if (Strings.isNotBlank(request.getAdminAreaCode())) {
            searcher.setAdminAreaCode(AdminAreaCodeUtils.getCutdAreaCode(request.getAdminAreaCode()) + "%");
        }
        searcher.setName(Strings.trimToNull(request.getName()));

        List<CareWelfareMerchantBO> careWelfareMerchantBOS = careWelfareMerchantInfoService.searchMerchantInfo(searcher);
        List<CareWelfareMerchantInfoDTO> result = Lists.newArrayList();

        for (CareWelfareMerchantBO careWelfareMerchantBO : careWelfareMerchantBOS) {
            CareWelfareMerchantInfoDTO dto = new CareWelfareMerchantInfoDTO();
            BeanUtils.copyProperties(careWelfareMerchantBO, dto);
            dto.setDistance(calculateDistance(request.getLatitude(), request.getLongitude(), careWelfareMerchantBO.getLatitude(), careWelfareMerchantBO.getLongitude()));
            result.add(dto);
        }

        return ResponseUtils.buildSuccessPagingResponse(result, searcher);
    }

    @Override
    public BasePagingResponse<List<CareWelfareMerchantInfoDTO>> searchMerchantInfoWithoutAuth(CareWelfareMerchantInfoSearchRequest request) {
        BizCheckUtil.checkNotNull(request, "request的请求参数不能为空");
        if (AdminAreaCodeEnum.NEAREST.name().equals(request.getAdminAreaCode()) || AdminAreaCodeEnum.NEAREST.name().equals(request.getSearchType())) {
            BasePagingResponse<List<CareWelfareMerchantInfoDTO>> nearestMerchant = getNearestMerchant(request);
            if (nearestMerchant != null) {
                for (CareWelfareMerchantInfoDTO merchantInfoDTO : nearestMerchant.getDto()) {
                    merchantInfoDTO.setStreet(careWelfareMerchantStreetProvider.getCachedStreet(merchantInfoDTO.getId()));
                    merchantInfoDTO.setFavorite(commonFavoriteProvider.cachedIsFavorite(CommonFavoriteTypeEnum.MERCHANT.name(), merchantInfoDTO.getId(), request.getSoldierId()));
                }
                return nearestMerchant;
            } else {
                request.setAdminAreaCode("330100000000");
            }
        }

        final CareWelfareMerchantInfoBSearcher searcher = CareWelfareMerchantInfoProviderConverter.convertRequestSO2Searcher(request);

        if (Strings.isNotBlank(request.getAdminAreaCode())) {
            searcher.setAdminAreaCode(AdminAreaCodeUtils.getCutdAreaCode(request.getAdminAreaCode()) + "%");
        }
        List<CareWelfareMerchantBO> careWelfareMerchantBOS = careWelfareMerchantInfoService.searchAllMerchantInfo(searcher);
        List<CareWelfareMerchantInfoDTO> result = Lists.newArrayList();

        for (CareWelfareMerchantBO careWelfareMerchantBO : careWelfareMerchantBOS) {
            CareWelfareMerchantInfoDTO dto = new CareWelfareMerchantInfoDTO();
            BeanUtils.copyProperties(careWelfareMerchantBO, dto);
            dto.setDistance(calculateDistance(request.getLatitude(), request.getLongitude(), careWelfareMerchantBO.getLatitude(), careWelfareMerchantBO.getLongitude()));
            dto.setStreet(careWelfareMerchantStreetProvider.getCachedStreet(dto.getId()));
            dto.setFavorite(commonFavoriteProvider.cachedIsFavorite(CommonFavoriteTypeEnum.MERCHANT.name(), dto.getId(), request.getSoldierId()));


            String locations = dto.getLocations();
            if (Strings.isNotBlank(locations) && Strings.isBlank(dto.getAddress())) {
                List<MerchantLocationItemBO> merchantLocationItemBOS = JSONArray.parseArray(locations, MerchantLocationItemBO.class);
                if (CollectionUtils.isNotEmpty(merchantLocationItemBOS)) {
                    dto.setAddress(merchantLocationItemBOS.get(0).getAddress());
                    dto.setLongitude(merchantLocationItemBOS.get(0).getLongitude());
                    dto.setLatitude(merchantLocationItemBOS.get(0).getLatitude());
                }
            }
            result.add(dto);
        }

        return ResponseUtils.buildSuccessPagingResponse(result, searcher);
    }

    @Override
    public BaseResponse<List<String>> listAllPublishedMerchant(CareWelfareMerchantInfoSearchRequest careWelfareMerchantInfoSearchRequest) {
        return null;
    }

    @Override
    public BaseResponse<CareWelfareMerchantInfoDTO> getCareWelfareMerchantInfo(BaseGetRequest baseGetRequest) {

        final BaseResponse<CareWelfareMerchantInfoDTO> baseResponse = new BaseResponse<>();
        serviceTemplate.execute(baseResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(baseGetRequest, "获取单条CareWelfareMerchantInfo的请求参数不能为空");
                BizCheckUtil.checkNotBlank((String) baseGetRequest.getId(), "id不能为空");
            }

            @Override
            public void executeService() {
                final CareWelfareMerchantInfoDTO remoteObj = getCareWelfareMerchantInfoDTO((String) baseGetRequest.getId());
                if (remoteObj != null) {
                    String locations = remoteObj.getLocations();
                    if (Strings.isNotBlank(locations) && Strings.isBlank(remoteObj.getAddress())) {
                        List<MerchantLocationItemBO> merchantLocationItemBOS = JSONArray.parseArray(locations, MerchantLocationItemBO.class);
                        if (CollectionUtils.isNotEmpty(merchantLocationItemBOS)) {
                            remoteObj.setAddress(merchantLocationItemBOS.get(0).getAddress());
                            remoteObj.setLongitude(merchantLocationItemBOS.get(0).getLongitude());
                            remoteObj.setLatitude(merchantLocationItemBOS.get(0).getLatitude());
                        }
                    }
                }

                ResponseUtils.setupSuccessResponse(baseResponse, remoteObj);
            }

            @Override
            public ScenarioCodeEnum getScenarioEnum() {
                return ScenarioCodeEnum.CARE_WELFARE_MERCHANT_INFO_GET;
            }
        });
        return baseResponse;
    }
    private CareWelfareMerchantInfoDTO getCareWelfareMerchantInfoDTO(String id) {
        final CareWelfareMerchantInfoDO careWelfareMerchantInfoDO = careWelfareMerchantInfoService.get(id);
        if (careWelfareMerchantInfoDO == null) {
            return null;
        }

        final CareWelfareMerchantInfoDTO remoteObj = CareWelfareMerchantInfoProviderConverter.convertResponseDO2DTO(careWelfareMerchantInfoDO);


        List<CareWelfareMerchantDiscountDO> careWelfareMerchantDiscountDOS = careWelfareMerchantDiscountService.listByMerchantId(careWelfareMerchantInfoDO.getId());
        final List<CareWelfareMerchantDiscountDTO> careWelfareMerchantDiscountDTOList = CareWelfareMerchantDiscountProviderConverter.
                convertResponseDOList2DTOList(careWelfareMerchantDiscountDOS);
        remoteObj.setDiscounts(careWelfareMerchantDiscountDTOList);

        remoteObj.setStreet(careWelfareMerchantStreetProvider.getCachedStreet(id));


        return remoteObj;
    }

    @Override
    public BaseResponse<CareWelfareMerchantInfoDTO> getCachedCareWelfareMerchantInfo(BaseGetRequest baseGetRequest) {
        return null;
    }

    @Override
    public BaseResponse<Integer> deleteCareWelfareMerchantInfo(BaseDeleteRequest deleteRequest) {
        return null;
    }

    @Override
    public BaseResponse<CareScanMerchantInfoResult> scanMerchantQr(SimpleApiRequest request) {
        BizCheckUtil.checkNotBlank(request.getQrString(), "qrstring不能为空");
        BizCheckUtil.checkNotBlank(request.getSoldierId(), "老兵不能为空");
        CareWelfareMerchantInfoDO merchantInfoDO = careWelfareMerchantInfoService.getByMerchantQrString(request.getQrString());

        return buildMerchantAndUserInfoResponse(request, merchantInfoDO);
    }

    @Override
    public BaseResponse<CareScanMerchantInfoResult> getMerchantUserMatchInfo(SimpleApiRequest request) {

        BizCheckUtil.checkNotBlank(request.getId(), "qrstring不能为空");
        BizCheckUtil.checkNotBlank(request.getSoldierId(), "老兵不能为空");

        CareWelfareMerchantInfoDO merchantInfoDO = careWelfareMerchantInfoService.get(request.getId());

        return buildMerchantAndUserInfoResponse(request, merchantInfoDO);
    }

    private BaseResponse<CareScanMerchantInfoResult> buildMerchantAndUserInfoResponse(SimpleApiRequest request, CareWelfareMerchantInfoDO merchantInfoDO) {
        SoldierUserInfoDTO userInfoDTO = null;
        try {
            userInfoDTO = soldierProvider.checkLbmInfo(request.getSoldierId()).getDto();
        } catch (BizException e) {
            return ResponseUtils.buildSuccessResponse(new CareScanMerchantInfoResult("1", "暂未获取老兵码"));
        }
        Set<String> soldierTypeSet = convertSoldierTypeToSet(userInfoDTO.getSoldierTypeDictCode());
        String residentAdminAreaCode = userInfoDTO.getResidentAdminAreaCode();


        if (merchantInfoDO == null) {
            return ResponseUtils.buildSuccessResponse(new CareScanMerchantInfoResult("1", "商家不存在"));
        }

        insertScanRecord(request, merchantInfoDO, userInfoDTO.getIdCardNo());

        final CareWelfareMerchantInfoDTO merchantInfoDTO = CareWelfareMerchantInfoProviderConverter.convertResponseDO2DTO(merchantInfoDO);
        List<CareWelfareMerchantDiscountDTO> discountList = Lists.newArrayList();


        List<CareWelfareMerchantDiscountDO> careWelfareMerchantDiscountDOS = careWelfareMerchantDiscountService.listByMerchantId(merchantInfoDO.getId());
        String errorMsg = "";
        for (CareWelfareMerchantDiscountDO careWelfareMerchantDiscountDO : careWelfareMerchantDiscountDOS) {
            if (careWelfareMerchantDiscountDO.getEffectiveAreaType().equals(1)) {
                if (!AdminAreaCodeUtils.checkPrefixSame(careWelfareMerchantDiscountDO.getEffectiveAreaCode(), residentAdminAreaCode, 6)) {
                    errorMsg = "当前地区无法享受";
                    continue;
                }
            }
            if (!checkInSoldierType(careWelfareMerchantDiscountDO.getSoldierTypeCodes(), soldierTypeSet)) {
                errorMsg = "当前老兵类型无法享受";
                continue;
            }

            CareWelfareMerchantDiscountDTO remoteObj = CareWelfareMerchantDiscountProviderConverter.convertResponseDO2DTO(careWelfareMerchantDiscountDO);

            discountList.add(remoteObj);
        }

        CareScanMerchantInfoResult result;
        if (CollectionUtils.isEmpty(discountList)) {
            result = new CareScanMerchantInfoResult("0", MerchantTypeEnum.getByEnumName(merchantInfoDTO.getType()).getErrorMsg() + "(" + errorMsg + ")");
        } else {
            result = new CareScanMerchantInfoResult("0", MerchantTypeEnum.getByEnumName(merchantInfoDTO.getType()).getSuccessMsg());
            String promotionMethods = discountList.stream().map(CareWelfareMerchantDiscountDTO::getPromotionMethod).collect(Collectors.joining(","));
            String enjoyModes = discountList.stream().map(CareWelfareMerchantDiscountDTO::getEnjoyMode).collect(Collectors.joining(","));
            merchantInfoDTO.setPromotionMethods(promotionMethods);
            merchantInfoDTO.setDiscounts(discountList);
            merchantInfoDTO.setEnjoyModes(enjoyModes);
        }

        result.setMerchantInfo(merchantInfoDTO);
        result.setSoldierInfo(userInfoDTO);

        return ResponseUtils.buildSuccessResponse(result);
    }
    private boolean checkInSoldierType(String soldierTypeCodes, Set<String> soldierTypeSet) {

        if (soldierTypeCodes.contains("ALL")) {
            return true;
        }

        String[] split = soldierTypeCodes.split(",");
        for (String s : split) {
            if (soldierTypeSet.contains(s.trim())) {
                return true;
            }
        }
        return false;
    }
    private void insertScanRecord(SimpleApiRequest request, CareWelfareMerchantInfoDO merchantInfoDO, String idCardNo) {
        ScanCodeRecordDO scanCodeRecordDO = new ScanCodeRecordDO();
        scanCodeRecordDO.setSoldierId(request.getSoldierId());
        scanCodeRecordDO.setIdCardNo(idCardNo);
        scanCodeRecordDO.setType(RecordTypeEnum.MERCHANT.name());
        scanCodeRecordDO.setBizType(merchantInfoDO.getType());
        scanCodeRecordDO.setBizId(merchantInfoDO.getId());
        scanCodeRecordDO.setBizName(merchantInfoDO.getName());
        scanCodeRecordDO.setLatitude(request.getLatitude());
        scanCodeRecordDO.setLongitude(request.getLongitude());
        scanCodeRecordService.insert(scanCodeRecordDO);
    }
    private Set<String> convertSoldierTypeToSet(String soldierTypeDictCode) {
        Set<String> set = Sets.newHashSet();
        if (Strings.isBlank(soldierTypeDictCode)) {
            return set;
        }
        String[] split = soldierTypeDictCode.split(",");
        for (String s : split) {
            set.add(s.trim());
        }
        return set;
    }

    private Integer calculateDistance(Double latitude, Double longitude, Double sjLat, Double sjLng) {
        if (latitude == null || longitude == null || sjLat == null || sjLng == null) {
            return null;
        }

        double distance = LocationUtils.getDistance(latitude, longitude, sjLat, sjLng);
        return (int) distance;
    }


    private BasePagingResponse<List<CareWelfareMerchantInfoDTO>> getNearestMerchant(CareWelfareMerchantInfoSearchRequest request) {
        Double latitude = request.getLatitude();
        Double longitude = request.getLongitude();

        if (latitude != null && longitude != null) {
            Map<String, CareWelfareMerchantBO> allCachedMerchantMap = getAllCachedMerchantMap();

            if (Strings.isNotBlank(request.getName())) {
                Map<String, CareWelfareMerchantBO> filterNameMap = Maps.newHashMap();
                for (Map.Entry<String, CareWelfareMerchantBO> entry : allCachedMerchantMap.entrySet()) {
                    if (entry.getValue().getName().contains(request.getName().trim())) {
                        filterNameMap.put(entry.getKey(), entry.getValue());
                    }
                }
                allCachedMerchantMap = filterNameMap;
            }


            if (Strings.isNotBlank(request.getAdminAreaCode()) && request.getAdminAreaCode().startsWith("33")) {
                String cutdAreaCode = AdminAreaCodeUtils.getCutdAreaCode(request.getAdminAreaCode());
                Map<String, CareWelfareMerchantBO> filterMap = Maps.newHashMap();
                for (Map.Entry<String, CareWelfareMerchantBO> entry : allCachedMerchantMap.entrySet()) {
                    if (entry.getValue().getAdminAreaCode().startsWith(cutdAreaCode)) {
                        filterMap.put(entry.getKey(), entry.getValue());
                    }
                }
                allCachedMerchantMap = filterMap;
            }


            if (Strings.isNotBlank(request.getType())) {
                Map<String, CareWelfareMerchantBO> filterMap = Maps.newHashMap();
                for (Map.Entry<String, CareWelfareMerchantBO> entry : allCachedMerchantMap.entrySet()) {
                    if (entry.getValue().getType().equals(request.getType().trim())) {
                        filterMap.put(entry.getKey(), entry.getValue());
                    }
                }
                allCachedMerchantMap = filterMap;
            }
            if (Strings.isNotBlank(request.getSubtype())) {
                Map<String, CareWelfareMerchantBO> filterMap = Maps.newHashMap();
                for (Map.Entry<String, CareWelfareMerchantBO> entry : allCachedMerchantMap.entrySet()) {
                    if (Strings.isNotBlank(entry.getValue().getSubtype()) && entry.getValue().getSubtype().equals(request.getSubtype().trim())) {
                        filterMap.put(entry.getKey(), entry.getValue());
                    }
                }
                allCachedMerchantMap = filterMap;
            }

            Map<String, Integer> distanceMap = Maps.newHashMap();
            for (CareWelfareMerchantBO careWelfareMerchantBO : allCachedMerchantMap.values()) {
                distanceMap.put(careWelfareMerchantBO.getId(), calculateDistance(latitude, longitude,
                        careWelfareMerchantBO.getLatitude(), careWelfareMerchantBO.getLongitude()));
            }
            List<Map.Entry<String, Integer>> entries = new ArrayList<>(distanceMap.entrySet());
            CollectionUtil.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
                @Override
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    return o1.getValue().compareTo(o2.getValue());
                }
            });


            List<Map.Entry<String, Integer>> sub = paging(request.getPageNo(), request.getPageSize(), entries);

            List<CareWelfareMerchantInfoDTO> result = Lists.newArrayList();
            for (Map.Entry<String, Integer> distanceEntry : sub) {
                CareWelfareMerchantBO careWelfareMerchantBO = allCachedMerchantMap.get(distanceEntry.getKey());
                CareWelfareMerchantInfoDTO dto = new CareWelfareMerchantInfoDTO();
                BeanUtils.copyProperties(careWelfareMerchantBO, dto);
                dto.setDistance(distanceEntry.getValue());
                result.add(dto);
            }

            return ResponseUtils.buildSuccessPagingResponse(result, request.getPageNo(), request.getPageSize(), allCachedMerchantMap.size());
        }

        return null;
    }

    public static <T> List<T> paging(Integer pageNo, Integer pageSize, List<T> list) {
        if (list == null) {
            list = new ArrayList<T>();
        }
        if (pageNo == null) {
            pageNo = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        if (pageNo <= 0) {
            pageNo = 1;
        }

        int totalitems = list.size();
        List<T> pagingList = new ArrayList<T>();

        int totalNum = ((pageNo - 1) * pageSize) + pageSize > totalitems ? totalitems : ((pageNo - 1) * pageSize) + pageSize;
        for (int i = (pageNo - 1) * pageSize; i < totalNum; i++) {
            pagingList.add(list.get(i));
        }
        return pagingList;
    }


    private void expiredMerchant(String id) {
        String key = "ALL_MERCHANT";
        Map<String, CareWelfareMerchantBO> merchants = cachedMerchants.getIfPresent(key);
        if (merchants != null) {
            merchants.remove(id);
        }
    }

    private Map<String, CareWelfareMerchantBO> getAllCachedMerchantMap() {
        String key = "ALL_MERCHANT";
        Map<String, CareWelfareMerchantBO> merchants = cachedMerchants.getIfPresent(key);
        if (merchants != null) {
            return merchants;

        }

        final CareWelfareMerchantInfoBSearcher searcher = new CareWelfareMerchantInfoBSearcher(1, Integer.MAX_VALUE);
        List<CareWelfareMerchantBO> careWelfareMerchantBOS = careWelfareMerchantInfoService.searchAllMerchantInfo(searcher);

        Map<String, CareWelfareMerchantBO> result = Maps.newHashMap();
        for (CareWelfareMerchantBO careWelfareMerchantBO : careWelfareMerchantBOS) {
            if (Strings.isNotBlank(careWelfareMerchantBO.getEntryId())) {
            }
            MerchantTypeEnum byEnumName = MerchantTypeEnum.getByEnumName(careWelfareMerchantBO.getType());
            careWelfareMerchantBO.setIcon(byEnumName.getImg());
            String locations = careWelfareMerchantBO.getLocations();
            if (Strings.isNotBlank(locations)) {
                List<MerchantLocationItemBO> merchantLocationItemBOS = JSONArray.parseArray(locations, MerchantLocationItemBO.class);
                int i = 0;
                for (MerchantLocationItemBO merchantLocationItemBO : merchantLocationItemBOS) {
                    CareWelfareMerchantBO merchantCopy = new CareWelfareMerchantBO();
                    SycBeanUtils.copyProperties(careWelfareMerchantBO, merchantCopy);
                    merchantCopy.setAddress(merchantLocationItemBO.getAddress());
                    merchantCopy.setLongitude(merchantLocationItemBO.getLongitude());
                    merchantCopy.setLatitude(merchantLocationItemBO.getLatitude());
                    merchantCopy.setId(careWelfareMerchantBO.getId() + "-" + String.valueOf(i++));
                    result.put(merchantCopy.getId(), merchantCopy);
                }
            } else {
                if (careWelfareMerchantBO.getLongitude() != null && careWelfareMerchantBO.getLatitude() != null) {
                    result.put(careWelfareMerchantBO.getId(), careWelfareMerchantBO);
                }
            }

        }

        cachedMerchants.put(key, result);
        return result;
    }








    private String getNextCode(String adminAreaCode) {
        BizCheckUtil.checkNotBlank(adminAreaCode, "地区不能为空");
        String code;
        String prefix = "NO.";
        if (AdminAreaCodeUtils.getCutdAreaCode(adminAreaCode).equals("3301")) {
            code = prefix + "00";
        } else {
            code = prefix + adminAreaCode.substring(4, 6);
        }
        code = code + "-";
        String maxCode = careWelfareMerchantInfoService.getMaxCode(code);
        int maxNo = extractNo(maxCode);
        String myNo = String.format("%05d", maxNo + 1);
        return code + myNo;
    }

    private int extractNo(String maxCode) {
        if (Strings.isBlank(maxCode)) {
            return 0;
        }
        return Integer.parseInt(maxCode.substring(6));
    }

    private void checkAndInsertMerchantUser(CareWelfareMerchantInfoDO careWelfareMerchantInfoDO) {
        String contactNo = careWelfareMerchantInfoDO.getContactNo();

        if (Strings.isNotBlank(contactNo) && CommonCheckUtils.checkNotChar(contactNo)) {
            MerchantUserDO oldUser = merchantUserService.getByMobile(contactNo);
            if (oldUser != null) {
                return;
            }

            MerchantUserDO merchantUserDO = new MerchantUserDO();
            merchantUserDO.setAvatarPath(careWelfareMerchantInfoDO.getLogo());
            merchantUserDO.setMerchantId(careWelfareMerchantInfoDO.getId());
            merchantUserDO.setMobile(contactNo);
            merchantUserDO.setPassword(PasswordUtils.encodeBySm3(contactNo, "cjxf123"));
            merchantUserDO.setStatus(UserStatusEnum.ENABLED.name());
            merchantUserService.insert(merchantUserDO);
        }
    }

    private String convertAdminAreaCodeFromAddress(String address) {
        String hzAreaCode = "330100000000";
        if (Strings.isEmpty(address)) {
            return hzAreaCode;
        }
        List<CommonAdminAreaDO> subAreaList = commonAdminAreaService.findSubAreaList(hzAreaCode);
        Map<String, String> valueMap = Maps.newHashMap();
        for (CommonAdminAreaDO commonAdminAreaDO : subAreaList) {
            String value = commonAdminAreaDO.getValue();
            value = removeCommonAreaChar(value);
            valueMap.put(value, commonAdminAreaDO.getId());
        }

        for (String s : valueMap.keySet()) {
            if (address.contains(s)) {
                return valueMap.get(s);
            }
        }
        return hzAreaCode;
    }

    private String removeCommonAreaChar(String value) {
        if (Strings.isEmpty(value)) {
            return value;
        }
        value = value.replace("市", "");
        value = value.replace("县", "");
        return value;
    }






}
